import threading
import socket
import wx
from socket import socket, AF_INET, SOCK_STREAM
class MyClient(wx.Frame):
    def __init__(self,client_name):
        #调用父类的初始化方法
        #None没有父级窗口，id表示当前窗口编号，pos窗体打开位置，size窗体大小，单位像素
        #wx.Frame.__init__(self,None,wx.ID_ANY,"",style=wx.DEFAULT_FRAME_STYLE)
        wx.Frame.__init__(self,None,id = 1001,title = client_name+'的客户端',pos = wx.DefaultPosition,size = (400,450))
        #创建面板对象
        pl = wx.Panel(self)
        #在面板上放置盒子
        box = wx.BoxSizer(wx.VERTICAL) #垂直方向布局
        #可伸缩的网络布局
        fgz1 = wx.FlexGridSizer(wx.HSCROLL) #水平方向布局
        #fgz1 = wx.FlexGridSizer(cols=3,hgap=10,vgap=10,)
        #创建两个按钮
        conn_btn = wx.Button(pl,size =(200,40),label = '连接')
        dis_conn_btn = wx.Button(pl,size =(200,40),label = '断开')
        #把两个按钮放到可伸缩的网络布局
        fgz1.Add(conn_btn,0,wx.Top|wx.LEFT)
        fgz1.Add(dis_conn_btn,0,wx.TOP|wx.RIGHT)
        #把可伸缩的网络布局添加到box中
        box.Add(fgz1,1,wx.ALIGN_CENTER)

        #只读文本框，显示聊天内容
        self.show_text = wx.TextCtrl(pl,size= (400,210),style=wx.TE_MULTILINE | wx.TE_READONLY)
        box.Add(self.show_text,1,wx.ALIGN_CENTER)
        #创建聊天内容的文本框
        self.chat_text = wx.TextCtrl(pl,size= (400,120),style=wx.TE_MULTILINE)
        box.Add(self.chat_text,1,wx.ALIGN_CENTER)

        # 可伸缩的网络布局
        fgz2 = wx.FlexGridSizer(wx.HSCROLL)  # 水平方向布局
        # fgz2 = wx.FlexGridSizer(cols=3,hgap=10,vgap=10,)
        # 创建两个按钮
        reset_btn = wx.Button(pl, size=(200, 40), label='重置')
        send_btn = wx.Button(pl, size=(200, 40), label='发送')
        # 把两个按钮放到可伸缩的网络布局
        fgz2.Add(reset_btn, 0, wx.Top | wx.LEFT)
        fgz2.Add(send_btn, 0, wx.TOP | wx.RIGHT)
        # 把可伸缩的网络布局添加到box中
        box.Add(fgz2, 1, wx.ALIGN_CENTRE)
        #将盒子放到面板中
        pl.SetSizer(box)
        '''以上代码是客户端界面绘制'''
        #连接按钮功能
        self.Bind(wx.EVT_BUTTON,self.connect_to_server,conn_btn)
        #实例属性的设置
        self.client_name = client_name
        #存储客户端连接服务器状态，默认为False
        self.isConnected = False
        #设置客户端的socket对象为空
        self.client_socket=None
        #重置按钮功能
        self.Bind(wx.EVT_BUTTON,self.reset_text,reset_btn)
        #发送按钮功能
        self.Bind(wx.EVT_BUTTON,self.send_data,send_btn)
        #断开连接按钮功能
        self.Bind(wx.EVT_BUTTON,self.disconnect_server,dis_conn_btn)
    def connect_to_server(self,event):

        #如果客户端没有连接服务器，则开始连接
        if not self.isConnected:
            #TCP编程的步骤

            #创建socket对象
            self.client_socket = socket(AF_INET,SOCK_STREAM)
            #发送连接请求
            try:
                self.client_socket.connect(('127.0.0.1',8888))
                #连接成功，发送一条数据
                print(f'客户端{self.client_name}连接服务器成功')
                self.client_socket.send(self.client_name.encode('utf-8'))
                #启动一个线程，客户端的线程与服务器会话线程进行通话
                client_thread = threading.Thread(target=self.recv_data)
                #设置为守护线程
                client_thread.daemon=True
                #修改连接状态
                self.isConnected = True
                #启动线程
                client_thread.start()
            except Exception as e:
                # 捕获异常，打印错误信息
                print("连接失败:", e)
            '''
            finally:
                #关闭socket连接
                self.client_socket.close()
                print('连接已关闭')
            '''
    def disconnect_server(self,event):
        if self.isConnected:
            #发送一条数据'---disconnect---'
            data = '---disconnect---'
            self.client_socket.send(data.encode('utf-8'))
            # 断开连接
            self.isConnected = False
        else:
            print('没有连接，请先连接')

    def recv_data(self):
        #判断是否连接状态
        while self.isConnected:
            #接收来自服务器的数据
            data = self.client_socket.recv(1024).decode('utf-8')
            #显示到只读文本框
            self.show_text.AppendText('-'*40+'\n'+data+'\n')
    def reset_text(self,event):
        self.chat_text.Clear()
    def send_data(self,event):
        #判断是否连接
        if self.isConnected:
            #获得文本框的发送数据
            send_data = self.chat_text.GetValue()
            #发送给服务器
            self.client_socket.send(send_data.encode('utf-8'))
            self.chat_text.Clear()



if __name__ == '__main__':
    #初始化app()
    app = wx.App()
    #创建自己的客户端界面对象
    my_client = MyClient('lf')
    my_client.Show()
    #循环刷新显示
    app.MainLoop()